package com.glsc.ngateway.opmanage.exception;

import com.glsc.ngateway.common.api.platform.resp.PlatformResponse;
import com.glsc.ngateway.opmanage.utils.DateUtils;
import com.glsc.ngateway.opmanage.service.MailService;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Arrays;
import java.util.stream.Collectors;

@ControllerAdvice
public class WebExceptionHandler {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private MailService mailService;

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public <T extends RuntimeException> PlatformResponse<Void> IllegalArgumentExceptionHandler(T e) {
        logger.error("异常", e);
        //logger.error("抛出RuntimeException异常：" + e.getClass().getSimpleName() + ",时间为：" + DateUtils.getCurrentDate(DateUtils.formatSecond));
        //logger.error("runtime异常", e);
        //mailService.sendMailToAdmin("运管opmanage异常", Arrays.toString(e.getStackTrace()));
        return PlatformResponse.failedMsg(e.getMessage());
    }

    /**
     * 处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public <T extends BindException> PlatformResponse<Void> bindExceptionHandler(T e) {
        logger.error("异常", e);
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return PlatformResponse.failedMsg(message);
    }

    /**
     * 处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是javax.validation.ConstraintViolationException
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public <T extends ConstraintViolationException> PlatformResponse<Void> constraintViolationExceptionHandler(T e) {
        logger.error("异常", e);
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        return PlatformResponse.failedMsg(message);
    }

    /**
     * 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常。
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public <T extends MethodArgumentNotValidException> PlatformResponse<Void> methodArgumentNotValidExceptionHandler(T e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return PlatformResponse.failedMsg(message);
    }

    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public <T extends RuntimeException> PlatformResponse<Void> runtimeExceptionHandler(T e) {
        logger.error("异常", e);
        logger.error("抛出RuntimeException异常：" + e.getClass().getSimpleName() + ",时间为：" + DateUtils.getCurrentDate(DateUtils.formatSecond));
        logger.error("runtime异常", e);
        mailService.sendMailToAdmin("运管opmanage异常", Arrays.toString(e.getStackTrace()));
        return PlatformResponse.failedMsg(e.getMessage());
    }


    @ExceptionHandler(PlatformException.class)
    @ResponseBody
    public <T extends PlatformException> PlatformResponse<Void> platformExceptionHandler(T e) {
        String errMsg = Strings.isNotBlank(e.getMsg()) ? e.getMsg() : "操作失败";
        logger.error(String.format("抛出PlatformException异常：%s, 时间为：%s, 错误信息：%s", e.getClass().getSimpleName(), DateUtils.getCurrentDate(DateUtils.formatSecond), errMsg));
        if (e.isPrintStackTraceFlag()) {
            logger.error("异常", e);
        }
        if(e.isSendMail2Admin()) {
            mailService.sendMailToAdmin("运管opmanage异常", Arrays.toString(e.getStackTrace()));
        }
        return PlatformResponse.failedMsg(Strings.isNotBlank(e.getMsg()) ? e.getMsg()
                : Strings.isNotBlank(e.getMessage()) ? e.getMessage()
                : "操作失败");
    }

    /**
     * @param e
     * @Description 500异常处理
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public <T extends Exception> PlatformResponse<?> exceptionHandler(T e) {
        logger.error("异常", e);
        logger.error("抛出Exception异常：" + e.getClass().getSimpleName() + ",时间为：" + DateUtils.getCurrentDate(DateUtils.formatSecond));
        logger.error("异常", e);
        mailService.sendMailToAdmin("运管opmanage异常", Arrays.toString(e.getStackTrace()));
        return PlatformResponse.failedMsg("Internal Server Error");
    }
}